package nl.rug.ai.mas.oops; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.net.URL; import java.util.Scanner; import javax.help.CSH; import javax.help.HelpBroker; import javax.help.HelpSet; import javax.help.SwingHelpUtilities; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.KeyStroke; import nl.rug.ai.mas.oops.lua.LuaProver; @SuppressWarnings("serial") public class GUI extends JFrame { private ScriptEditor d_editor; private Console d_console; private JMenuItem d_saveItem; private JMenuItem d_refreshItem; private String d_licenseText; private HelpBroker d_helpBroker; public GUI() { super("OOPS Graphical Environment"); readLicenseText(); initializeHelp(); setJMenuBar(buildMenuBar()); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { quitApplication(); } }); JFrame panel = this; setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.FIRST_LINE_START; c.gridx = 1; c.gridy = 1; c.gridwidth = 1; c.gridheight = 1; c.ipadx = 5; c.ipady = 5; panel.add(new JLabel("Editor"), c); c.gridx = 2; c.fill = GridBagConstraints.HORIZONTAL; c.gridy = 2; c.gridx = 1; c.gridwidth = 2; c.weighty = 0.7; c.weightx = 1.0; c.fill = GridBagConstraints.BOTH; d_editor = new ScriptEditor(); panel.add(d_editor.getComponent(), c); c.gridy = 3; c.gridwidth = 1; c.fill = GridBagConstraints.HORIZONTAL; c.weighty = 0.0; c.weightx = 0.0; panel.add(new JLabel("Console Output"), c); c.gridy = 4; c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.weighty = 0.3; c.weightx = 1.0; JScrollPane consolePane = new JScrollPane(); d_console = new Console(); d_console.setFont(new Font("Monospaced", Font.PLAIN, 11)); d_console.setEditable(false); consolePane.setViewportView(d_console); panel.add(consolePane, c); d_console.start(); try { System.setOut(new PrintStream(d_console.getOutputStream())); System.setErr(new PrintStream(d_console.getErrorStream())); } catch (IOException e) { showError(e, "Error Initializing Console"); } } // Thanks, http://stackoverflow.com/questions/309424/ static String slurp(java.io.InputStream is) { java.util.Scanner s = new Scanner(is, "UTF-8"); s.useDelimiter("\\A"); String str = s.hasNext() ? s.next() : ""; s.close(); return str; } private void readLicenseText() { try { InputStream resource = GUI.class.getClassLoader().getResourceAsStream("nl/rug/ai/mas/oops/LICENSE"); if (resource != null) { d_licenseText = slurp(resource); } } catch (Exception e) { System.err.println("Failed to read LICENSE: " + e); } } private void initializeHelp() { try { SwingHelpUtilities.setContentViewerUI("nl.rug.ai.mas.oops.ExternalLinkContentViewerUI"); URL url = HelpSet.findHelpSet(GUI.class.getClassLoader(), "nl/rug/ai/mas/oops/OopsHelp.hs"); HelpSet hs = new HelpSet(null, url); d_helpBroker = hs.createHelpBroker(); } catch (Exception e) { System.err.println(e); } } private void showError(Exception e, String title) { JOptionPane.showMessageDialog(this, title + " \n" + e.getMessage(), title, JOptionPane.ERROR_MESSAGE); } protected void quitApplication() { this.dispose(); System.exit(0); } private JMenuBar buildMenuBar() { JMenuBar menuBar = new JMenuBar(); menuBar.add(buildFileMenu()); menuBar.add(buildEditMenu()); menuBar.add(buildRunMenu()); menuBar.add(buildHelpMenu()); return menuBar; } private JMenu buildHelpMenu() { JMenu menu = new JMenu("Help"); JMenuItem manual = new JMenuItem("Manual"); manual.addActionListener(new CSH.DisplayHelpFromSource(d_helpBroker)); menu.add(manual); JMenuItem license = new JMenuItem("License"); license.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { showLicenseDialog(); } }); menu.add(license); return menu; } private JMenu buildRunMenu() { JMenu runMenu = new JMenu("Run"); JMenuItem runItem = buildMenuItem("Execute", 'E', KeyEvent.VK_E, false); runItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { runEditorContents(); } }); runMenu.add(runItem); JMenuItem clearItem = buildMenuItem("Clear console", 'C', KeyEvent.VK_E, true); clearItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { clearConsole(); } }); runMenu.add(clearItem); return runMenu; } protected void runEditorContents() { String text = d_editor.getText(); LuaProver prover = new LuaProver(); prover.doStream(new ByteArrayInputStream(text.getBytes()), "EditorContents"); while (!d_console.streamsFlushed()) { try { Thread.sleep(100); } catch (InterruptedException e) { showError(e); } } System.out.println("\n ============================= Run completed =============================\n"); } protected void clearConsole() { d_console.clear(); } private JMenu buildEditMenu() { JMenu editMenu = new JMenu("Edit"); JMenuItem undoItem = buildMenuItem("Undo", 'U', KeyEvent.VK_Z, false); undoItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { d_editor.undo(); } }); editMenu.add(undoItem); JMenuItem redoItem = buildMenuItem("Redo", 'R', KeyEvent.VK_Y, false); redoItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { d_editor.redo(); } }); editMenu.add(redoItem); editMenu.addSeparator(); JMenuItem cutItem = buildMenuItem("Cut", 't', KeyEvent.VK_X, false); cutItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { d_editor.cut(); } }); editMenu.add(cutItem); JMenuItem copyItem = buildMenuItem("Copy", 'C', KeyEvent.VK_C, false); copyItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { d_editor.copy(); } }); editMenu.add(copyItem); JMenuItem pasteItem = buildMenuItem("Paste", 'P', KeyEvent.VK_V, false); pasteItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { d_editor.paste(); } }); editMenu.add(pasteItem); return editMenu; } private JMenu buildFileMenu() { JMenu fileMenu = new JMenu("File"); // New file JMenuItem newItem = buildMenuItem("New", 'N', KeyEvent.VK_N, false); newItem.setEnabled(true); newItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { newFile(); } }); fileMenu.add(newItem); // Open file JMenuItem openItem = buildMenuItem("Open", 'O', KeyEvent.VK_O, false); openItem.setEnabled(true); openItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { openFile(); } }); fileMenu.add(openItem); fileMenu.addSeparator(); // Save file JMenuItem saveItem = buildMenuItem("Save", 'S', KeyEvent.VK_S, false); saveItem.setEnabled(false); saveItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveFile(); } }); fileMenu.add(saveItem); d_saveItem = saveItem; // Save file as JMenuItem saveAsItem = buildMenuItem("Save As", 'A', KeyEvent.VK_S, true); saveAsItem.setEnabled(true); saveAsItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { saveFileAs(); } }); fileMenu.add(saveAsItem); fileMenu.addSeparator(); // Refresh file (reload from file system) JMenuItem refreshItem = buildMenuItem("Refresh", 'R', KeyEvent.VK_R, false); refreshItem.setEnabled(false); refreshItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { refreshFile(); } }); fileMenu.add(refreshItem); d_refreshItem = refreshItem; fileMenu.addSeparator(); // Exit program JMenuItem exitItem = buildMenuItem("Exit", 'E', KeyEvent.VK_Q, false); exitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { quitApplication(); } }); fileMenu.add(exitItem); return fileMenu; } private void refreshFile() { try { d_editor.load(); } catch (IOException e) { showError(e); } updateEnabledMenuItems(); } private void saveFileAs() { JFileChooser fc = new JFileChooser(); int result = fc.showSaveDialog(this); if (result == JFileChooser.APPROVE_OPTION) { d_editor.setFile(fc.getSelectedFile()); try { d_editor.write(); } catch (IOException e) { showError(e); } } updateEnabledMenuItems(); } private void saveFile() { try { d_editor.write(); } catch (IOException e) { showError(e); } updateEnabledMenuItems(); } private void openFile() { JFileChooser fc = new JFileChooser(); int result = fc.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { d_editor.setFile(fc.getSelectedFile()); try { d_editor.load(); } catch (IOException e) { showError(e); } } updateEnabledMenuItems(); } private void showError(Exception e) { showError(e, "Error"); } private void newFile() { d_editor.setFile(null); d_editor.clear(); updateEnabledMenuItems(); } private void updateEnabledMenuItems() { boolean enabled = d_editor.getFile() != null; d_saveItem.setEnabled(enabled); d_refreshItem.setEnabled(enabled); } /** * Build a menu item without key accelerator. * * @param title * @param mnemnonic * @return */ private JMenuItem buildMenuItem(String title, char mnemonic) { JMenuItem item = new JMenuItem(title); item.setMnemonic(mnemonic); return item; } /** * Build a menu item with key accelerator. * * @param title * @param mnemonic * @param accelerator * @param shift * @return */ private JMenuItem buildMenuItem(String title, char mnemonic, int accelerator, boolean shift) { JMenuItem item = buildMenuItem(title, mnemonic); int keyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); if (shift) { keyMask = keyMask | KeyEvent.SHIFT_MASK; } item.setAccelerator(KeyStroke.getKeyStroke(accelerator, keyMask, false)); return item; } private void showLicenseDialog() { JDialog jDialog = new JDialog(this, "OOPS license", true); JTextArea jTextArea = new JTextArea(d_licenseText); jTextArea.setFont(new Font("Monospaced", Font.PLAIN, 11)); jTextArea.setEditable(false); jDialog.add(jTextArea); jDialog.pack(); jDialog.setLocationRelativeTo(this); jDialog.setVisible(true); } public static void main(String args[]) { JFrame window = new GUI(); window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); window.pack(); window.setMinimumSize(new Dimension(200, 300)); window.setSize(new Dimension(550, 700)); window.setVisible(true); } }